package cn.biplam.front.template.base;

import cn.biplam.common.paramters.SysName;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.front.html.HtmlDiv;
import cn.biplam.front.html.HtmlIFrame;
import cn.biplam.front.html.HtmlValue;
import cn.biplam.front.html.base.HtmlWindow;
import cn.biplam.front.html.base.Const.Float_Type;
import cn.biplam.front.html.base.Const.Position_Mode;
import cn.biplam.front.html.base.Const.Visibility_Mode;
import cn.biplam.front.html.base.Const.Window_Event;
import cn.biplam.front.template.Template;

/**
 * 文件上传模板<BR>
 * 原理：显示区分为按钮,文件名称,和文件上传IFrame(显示隐藏).	IFrame中提供Form和InputFile,由外部命令操作浏览文件和上传.
 * <P>使用说明：<UL>
 * <LI>第一步：创建<OL><LI>FileUpLoad upload=new FileUpLoad(页面ID,字段名称,浏览按钮的标题,sHomeUrl);</OL>
 * <LI>第二步：放置文件上传控件<OL><LI>假定父容器变量为"div"： div.put(upload.get());</OL>
 * <LI>第三步：设置信号灯<OL><LI>取信号灯：HtmlValue signal=upload.getSignal(调用页面的提交按钮ID);
 * 	 <LI>如果有多个文件上传控件,需要为后续每个设置信号灯：<BR>
 *  upload2.setSignal(signal,调用页面的提交按钮ID);</OL>
 * <LI>第四步：将窗口提交命令绑定到信号灯<OL><LI>upload.bindSubmit(调用页面的提交按钮ID,signal,窗口提交命令文本));<BR>
 * 		可以用任意一个文件上传控件的bindSubmit,但只能绑定一次<BR>
 * 		注意事项：窗口提交命令文本 是直接执行的脚本.</OL>
 * <LI>第五步：放置信号灯<OL><LI>假定父容器变量为"div"：div.put(signal);</OL>
 * </UL></UL>
 * <P>典型用例：文件上传页面一般在Prompt页面中调用,本例即是：<BR>
 * FileUpLoad logic=new FileUpLoad(cId+"f1","logicfile","浏览",sHomeUrl);<BR>
 * FileUpLoad physc=new FileUpLoad(cId+"f2","physcfile","浏览",sHomeUrl);<BR>
 * div.put(logic.get());<BR>
 * div.put(physc.get());<BR>
 * HtmlValue signal=logic.getSignal(SysName.PromptSubmitID);<BR>
 * physc.setSignal(signal,SysName.PromptSubmitID);<BR>
 * physc.bindSubmit(SysName.PromptSubmitID,signal,ScriptPrompt.submit(cId, ActionID));<BR>
 * div.put(signal);<BR>
 * 
 * @author 	WangSong 2009-6-9 下午08:29:41
 * @version 1.0
 */
public class FileUpLoad implements Template{

	/** 页面ID*/
	private String ID;
	/** 显示文件名称的页面对象的ID*/
	private String sTextID;
	/** 文件上传IFrame的ID*/
	private String sIFrameID;
	/** 存放文件入库后ID的字段控件的ID*/
	private String sFieldID;
	
	/** 整体容器*/
	private HtmlDiv div;
	/** 按钮名称*/
	private String sLabel;
	/** 主页路径*/
	private String sHomeUrl;
	/** 存放文件入库后ID的字段控件(HtmlValue)*/
	private String sFieldName;

	/**
	 * 构造方法
	 * @param ID			页面ID
	 * @param sName			显示的标签名称
	 * @throws ErrorMessage
	 */
	public FileUpLoad(String ID,String sFieldName,String sLabel,String sHomeUrl) throws ErrorMessage{
		this.sHomeUrl=sHomeUrl;
		this.sLabel=sLabel;
		this.ID=ID;
		this.sTextID=ID+"t";
		this.sIFrameID=ID+"i";
		this.sFieldID=ID+"f";
		this.sFieldName=","+sFieldName;
		this.div=new HtmlDiv(this.ID);
	}

	/**
	 * 创建浏览按钮,点击事件为调用IFrame中InputFile的click()
	 */
	private HtmlWindow createButton() throws ErrorMessage{
		HtmlWindow label=new Anchor("",this.sLabel).get();		//创建按钮
		label.bind(Window_Event.OnClick, "uploadOpen('"+this.ID+"');");
		label.setFloat(Float_Type.Left);
		return label;
	}
	
	/**
	 * 创建显示文件名称的页面对象
	 */
	private HtmlWindow createText() throws ErrorMessage{
		HtmlWindow text=new Text("",this.sTextID).get();		//创建文件名显示
		text.setFloat(Float_Type.Left);
		return text;
	}
	
	/**
	 * 创建文件上传IFrame
	 */
	private HtmlWindow createIFrame() throws ErrorMessage{
		HtmlIFrame iframe=new HtmlIFrame(this.sIFrameID);	//创建IFrame
		iframe.setVisibility(Visibility_Mode.Hidden);	//设置为隐藏
		iframe.setPositionMode(Position_Mode.Absolute);
		iframe.setTarget(this.sHomeUrl+SysName.UpLoadPort+"?id="+this.ID);
		return iframe;
	}
	
	/**
	 * 创建存储上传入库后的文件ID的字段
	 */
	private HtmlValue createField() {
		return new HtmlValue(this.sFieldID,this.sFieldName,null);
	}
	
	/**
	 * 功能：返回设置好的HtmlWindow对象
	 * @return	HtmlWindow
	 * @throws ErrorMessage 
	 */
	public HtmlWindow get() throws ErrorMessage{
		this.div.put(this.createButton());
		this.div.put(this.createText());
		this.div.put(this.createIFrame());
		this.div.put(this.createField());
		return this.div;
	}
	
	/**
	 * 将窗口提交命令绑定到信号灯，由信号灯控制所有文件上传结束后执行窗口提交命令
	 * @param submitButtonID	窗口的提交按钮ID
	 * @param signal			文件上传信号灯控件
	 * @param sScript			窗口提交的命令脚本(直接执行的脚本命令)
	 * @throws ErrorMessage 
	 */
	public void bindSubmit(String submitButtonID,HtmlValue signal,String sScript) throws ErrorMessage{
		signal.bind(signal.getID(),Window_Event.OnClick,sScript);
		signal.bind(signal.getID(),Window_Event.OnPropertyChange, "signalSubmit(this);");
	}
	
	/**
	 * 返回控制文件上传提交的信号灯控件
	 * @param submitButtonID	窗口的提交按钮ID
	 * @return	HtmlValue
	 * @throws ErrorMessage
	 */
	public HtmlValue getSignal(String submitButtonID) throws ErrorMessage{
		//name=需要提交的总文件数量,value=已提交成功的文件数量
		HtmlValue signal=new HtmlValue(this.ID+"signal"+"count","1","0");
		this.bindSignal(signal, submitButtonID);
		return signal;
	}
	
	/**
	 * 将本控件绑定到文件上传提交的信号灯控件上
	 * @param signal			文件上传信号灯控件
	 * @throws ErrorMessage 
	 */
	public void setSignal(HtmlValue signal,String submitButtonID) throws ErrorMessage{
		//增加信号灯的总文件数量计数器
		signal.setName(String.valueOf(Integer.valueOf(signal.getName())+1));
		//将多重绑定脚本绑定在信号灯上,实际执行是绑定到本文件上传控件的隐藏字段上
		this.bindSignal(signal, submitButtonID);
	}
	
	private void bindSignal(HtmlValue signal,String submitButtonID) throws ErrorMessage{
		//逻辑：当本控件的隐藏字段值发生变化(上传成功回写文件ID)时,修改信号灯的值+1,将触发信号灯控件的OnPropertyChange事件
		signal.bind(this.sFieldID, Window_Event.OnPropertyChange, "signalAdd('"+this.sTextID+"','"+signal.getID()+"')");
		//将文件上传控件的提交命令绑定到窗口提交按钮上(多重绑定)
		signal.bind(submitButtonID,Window_Event.OnClick,"upload('"+this.ID+"');");
		
	}

}
